#!/usr/bin/env python
#-*- coding: UTF-8 -*-
# utils.py: utils used in DTask
#
# Copyright (C) 2008-2010 Hily Jiang <hilyjiang@gmail.com>
#
# This file is part of dtask.
#
# This software is provided 'as-is', without any express or implied
# warranty.  In no event will the authors be held liable for any damages
# arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not
#    claim that you wrote the original software. If you use this software
#    in a product, an acknowledgment in the product documentation would be
#    appreciated but is not required.
# 2. Altered source versions must be plainly marked as such, and must not be
#    misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.

"""
utils used in DTask.
"""

import re


class CommandTools(object):
    """Tools to analyse command."""
    p_command = re.compile('[A-Z]+\n|[A-Z]+[\s]+[^\n]+\n')
    p_command_param = re.compile('^([A-Z]+)[\s]+([^\n]+)\n$')
    p_command_noparam = re.compile('^([A-Z]+)\n$')

    @staticmethod
    def findCommand(data):
        """Analyse commands from data."""
        # match all commands
        cmdStrs = CommandTools.p_command.findall(data)
        commandList = []
        for cmdStr in cmdStrs:
            cmdField = CommandTools.p_command_param.match(cmdStr)
            if cmdField:
               cmdField = cmdField.groups()
               # format: (command, params)
               commandList.append((cmdField[0], cmdField[1]))
            else:
               cmdField = CommandTools.p_command_noparam.match(cmdStr).groups()
                # format: (command, None)
               commandList.append((cmdField[0], None))
        return commandList

    @staticmethod
    def cleanCommand(data):
        """Clean the data that has already analyzed."""
        # remove the analyzed data
        data = CommandTools.p_command.sub('', data)

        # remove the unknown string
        if '\n' in data:
            data = data[data.rfind('\n'):]
        return data


class CommandBuffer(object):
    """Buffer to receive command string from socket and analyse commands."""

    def __init__(self):
        self.recvBuf = ''
        self.commandList = []

    def addData(self, data):
        """Add data to data receive buffer, and analyse commands."""
        self.recvBuf += data
        self.commandList.extend(CommandTools.findCommand(self.recvBuf))
        self.recvBuf = CommandTools.cleanCommand(self.recvBuf)

    def getCommand(self):
        """Pop a command out of the command list."""
        if len(self.commandList):
            cmdInfo = self.commandList[0]
            del self.commandList[0]
            return cmdInfo
        else:
            return None
